#ifndef _ARCHIVO_H_
#define _ARCHIVO_H_

/********************************************************************
 * Archivo.h
 * 
 * Descripcion :Esta clase representa una interfaz comun para todos 
 * los archivos.
 * - Tiene un registro modelo, es decir, un registro base para crear
 * registros del archivo.
*********************************************************************/

typedef enum TiposArchivo{HASH, SECUENCIAL, SECUENCIAL_INDEXADO, INDEXADO, 
						  ESPACIO_LIBRE, HEADER, CONTROL, NINGUNO, INDEXADO_SECUNDARIO, 
						  HASH_SECUNDARIO,SECUENCIAL_INDEXADO_SECUNDARIO, OVERFLOW_HASH,
						  INDICE_B, INDICE_B_MAS};

#include "tipo_struct.h"
#include "excep_creando_arch.h"
#include "excep_abriendo_arch.h"
#include "excep_arch_cerrado.h"
#include "excep_parser_sintaxis.h"
#include "excep_arch_inexistente.h"
#include "excep_bloque_tam.h"
#include "excep_reg_existente.h"
#include "excep_reg_inexistente.h"
#include "manejadorArchivos.h"
#include "manejadorErrores.h"
#include "funcProcStructCrear.h"
#include "funcProcAtomCrear.h"
#include "debugger.h"
#include "observable.h"
#include "bloque.h"
#include <cerrno>

class IndiceSec;

class Archivo : public Observable {
	
	friend class ArchivosFactory;
	
	private:
		std::string nombre;
		TipoStruct * reg_base; //Registro base del archivo
			
		//Constructor de copia privado: Para que no se puedan copiar los archivos.
		Archivo(const Archivo &a){}
		
		//Operador = privado: Para que no se puedan asignar archivos (y generar copias).
		Archivo& operator= (const Archivo &a) { return *this; }
				
	protected:
		
		unsigned int tam_bloque;
		unsigned int tam_bloque_indice;
		
		int fd;
		
		unsigned int cant_bloques;
		
	public:
		
		/*
		 * Parsea su registro base y lo carga en el archivo.
		 */ 
		void cargar_registro_base(std::string formato_reg) throw(ExcepSintaxisParser);
		
		/*
		 * Constructor: Inicializa la clase archivo con los datos necesarios.
		 * Inicialmente el archivo esta cerrado y el fd vale -1.
		 * Recibe el nombre, y el tamaño del
		 * bloque utilizado para almacenar fisicamente los datos.
		 */ 
		Archivo(std::string& nombre, unsigned int tam_bloque, unsigned int tam_bloque_indice = 0);
		
		/*
		 * Destructor de la clase. Si el archivo esta abierto, lo cierra.
		 */ 
		virtual ~Archivo();
				
		/*
		 * Devuelve un clon del registro modelo para poder ser llenado
		 * y utilizado. Debe ser liberado.
		 */ 
		TipoStruct * get_registro_base();
		
		/*
		 * Devuelve la cantidad de bloques que hay en el archivo hasta 
		 * el momento.
		 */
		unsigned int get_cant_bloques();
		
		/* 
		 * Devuelve el nombre del archivo
		 */ 
		std::string& get_nombre();
		
		/*
		 * Devuelve el file descriptor asociado al archivo.
		 * Si vale -1 es porque el archivo esta cerrado o es invalido.
		 */
		int get_fd();
		
		/*
		 * Devuelve el tamanio de bloques del archivo.
		 */
		unsigned int get_tam_bloque();
		
		/*
		 * Devuelve el tamanio de bloques del indice primario del archivo.
		 */
		unsigned int get_tam_indice();
		
		/*
		 * Abre fisicamente el archivo.
		 */ 
		virtual void abrir() throw(ExcepAbriendoArch) = 0;
		
		/*
		 * Cierra un archivo.
		 */
		virtual void cerrar() = 0;
 		
 		/*
 		 * Elimina el archivo fisicamente.
 		 */
 		virtual void eliminar() = 0;
 		
 		/*
 		 * Devuelve el tipo de archivo.
 		 */
 		virtual TiposArchivo get_tipo_archivo() = 0;
 		
 		/*
 		 * Devuelve el tamano ocupado por el archivo, en bytes
 		 */ 
 		 virtual long get_tam() throw(ExcepArchCerrado);
 		 
 		 /*
 		  * Devuelve el espacio libre en bytes
 		  */ 
 		 virtual unsigned int get_espacio_libre()  throw(ExcepArchCerrado, ExcepLeerBloque) = 0;
 		 
 		 /*
 		  * Operador == : Sirve para comprar 2 archivos. Si tienen el mismo nombre devuelve true,
 		  * sino devuelve false.
 		  */
 		  bool operator==(const Archivo& a2) const;  
 		 
 		 /*
 		  * Devuelve un TipoStruct cargado con el formato pasado por param.
 		  * Debe ser liberada la memoria.
 		  */ 
 		 TipoStruct * generar_reg_base(std::string& formato);
 		 
};

#endif
